package org.jground.rx.ui.zk;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jground.rx.IRXObject;
import org.jground.rx.IRXObjectSynopsis;
import org.jground.rx.RXDataState;
import org.jground.rx.RXObjectService;
import org.jground.rx.RXSearchCriteria;
import org.jground.rx.RXTypeRef;
import org.jground.rx.filter.RXContext;
import org.jground.rx.ui.IMainPanel;
import org.jground.util.CollectionUtils;
import org.jground.util.L;
import org.jground.util.StringUtils;
import org.jground.zk.zulX.GridX;
import org.jground.zk.zulX.HboxX;
import org.jground.zk.zulX.PanelX;
import org.jground.zk.zulX.VboxX;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Radio;
import org.zkoss.zul.Textbox;

public class UIDataObjectRefSearchPanel  implements EventListener, IMainPanel<Component> {

    //
    // CLASS LEVEL
    //
    public static final String ON_DONE = "onDone";
    public static final String ON_CANCEL = "onCancel";
    private static Log logger = LogFactory.getLog(UIDataObjectRefSearchPanel.class);
    public static String CANCEL = "Cancel";
    public static String DONE = "Done";
    public static int PAGE_SIZE = 20;
    //
    // OBJECT LEVEL
    //
    private UIFrame uiFrame;
    private Textbox queryTf;

    //
    private Button searchBt;
    private Button resetBt;
    //

    private Label resultLabel;
    private UIResultList resultList;
    private VboxX resultVbox;

    //
    private Button doneBt;
    private Button cancelBt;
    private EventListener callbackListener;

    //
    private RXSearchCriteria searchCriteria;
    private boolean multipleSelection;
    private List<IRXObjectSynopsis> selectedRXDataObjects;
    
    private PanelX view;

    public UIDataObjectRefSearchPanel(UIFrame frame) {
        logger.debug("start init");
        this.uiFrame = frame;
        //
        // CREATE
        //
        view = new PanelX();
        view.setTitle("Search");
        view.setCollapsible(true);
        searchCriteria = new RXSearchCriteria();
        //
        queryTf = new Textbox();
        //
        searchBt = new Button("Search");
        resetBt = new Button("Reset");
        doneBt = new Button("Done");
        cancelBt = new Button("Cancel");
        //
        resultLabel = new Label();

        resultList = new UIResultList(uiFrame, new ArrayList<IRXObjectSynopsis>());
        resultList.setPageSize(PAGE_SIZE);

        resultList.setPostfixRenderer(new PostfixRenderer());
        resultVbox = new VboxX(UIResultList.uiBox(resultList));
        //
        // LAYOUT
        //
        // GRID for search criteria
        GridX grid = new GridX("260px", "99%");

        view.add(grid);
        // SEARCH TEXT
        grid.addAsRow(new Label("Search Text"), queryTf);
        // BUTTONS
        HboxX hbox = null;
        view.add(hbox = new HboxX(searchBt, resetBt));

        hbox.setSclass(UIStyles.BUTTONGROUP);
        //
        resultVbox.add(hbox = new HboxX(doneBt, cancelBt));
        hbox.setSclass(UIStyles.BUTTONGROUP);
        view.add(resultVbox);
        //
        //
        // EVENTS
        //
        doneBt.addEventListener(Events.ON_CLICK, this);
        cancelBt.addEventListener(Events.ON_CLICK, this);
        searchBt.addEventListener(Events.ON_CLICK, this);
        resetBt.addEventListener(Events.ON_CLICK, this);
        view.addForward(Events.ON_OK, searchBt, Events.ON_CLICK);
        
        
        //

    }

    public void reInit(String title, boolean multipleSelection, EventListener listener,
            Collection<? extends IRXObjectSynopsis> selected, RXTypeRef typeRef, IRXObject dataContext) {
        Set<String> submoids = typeRef.getRefClasses();

        String[] moids = submoids.toArray(StringUtils.EMPTY_STRING_ARRAY);
        view.setTitle(title);
        this.multipleSelection = multipleSelection;
        searchCriteria.clear();
        if (typeRef.getFilter() != null) {
            searchCriteria.addFilter(new RXContext(dataContext), typeRef.getFilter());
        }
        searchCriteria.addIncludedMoids(moids);
        searchCriteria.addIncludedDataStates(RXDataState.APPROVED, RXDataState.STORED);
        selectedRXDataObjects = new ArrayList<IRXObjectSynopsis>(selected);
        this.callbackListener = listener;
        resetGUI();
    }

    public void doSearch() {
        String searchString = this.queryTf.getText().trim();
        searchCriteria.setSearchString(searchString);
        logger.debug(searchCriteria);
        List<IRXObjectSynopsis> result = RXObjectService.getInstance().search(searchCriteria);
        L.debug(logger, "result list ", result.size());
        resultLabel.setValue("Found " + result.size() + " elements.");
        this.resultList.removeAllObject();
        this.resultList.addObjects(result);
    }

    public void onEvent(Event e) throws Exception {
        if (e.getTarget() == searchBt) {
            doSearch();
        }
        if (e.getTarget() == resetBt) {
            queryTf.setValue("");
            resultLabel.setValue("");
        } else if (e.getTarget() == this.resetBt) {
            resetGUI();
        } else if (e.getTarget() == doneBt) {
            resetGUI();
            callbackListener.onEvent(new Event(ON_DONE, view));
        } else if (e.getTarget() == cancelBt) {
            resetGUI();
            callbackListener.onEvent(new Event(ON_CANCEL, view));
        } else if (e.getTarget() instanceof Radio) {
            Radio r = (Radio) e.getTarget();
            IRXObject mod = (IRXObject) r.getAttribute("mod");
            this.selectedRXDataObjects.clear();
            this.selectedRXDataObjects.add(mod);
            resetGUI();
            callbackListener.onEvent(new Event(ON_DONE, view));
        } else if (e.getTarget() instanceof Checkbox) {
            Checkbox cb = (Checkbox) e.getTarget();
            IRXObject mod = (IRXObject) cb.getAttribute("mod");
            if (cb.isChecked()) {
                CollectionUtils.addUnique(selectedRXDataObjects, mod);
            } else {
                selectedRXDataObjects.remove(mod);
            }
        }
    }

    private void resetGUI() {
        queryTf.setValue("");
    }

    private class PostfixRenderer implements ListitemRenderer {

        public void render(Listitem item, Object data) throws Exception {
            if (data instanceof IRXObject) {
                Listcell c = null;
                Checkbox cb = null;
                if (multipleSelection) {
                    cb = new Checkbox();
                } else {
                    cb = new Radio();
                }
                c = new Listcell();
                c.setParent(item);
                cb.setParent(c);
                cb.setAttribute("mod", data);
                cb.setChecked(selectedRXDataObjects.contains(data));
                cb.addEventListener(Events.ON_CHECK, UIDataObjectRefSearchPanel.this);
            }
        }

    }

    //
    // IMainPanel
    //

    public Component getView() {
        return view;
    }

    public void beforeShow() {
        doSearch();
    }

    public void beforeClose() {
        resetGUI();
    }

    public List<IRXObjectSynopsis> getSelected() {
        return selectedRXDataObjects;
    }

}